/*
 * VotingActions.cpp
 *
 *  Created on: Oct 12, 2011
 *      Author: kimi
 */

#include "VotingActions.h"

VotingActions::VotingActions(string filePath) {
	props = new Properties(filePath);
	props->load();

	votingHelper = new VotingHelper(props);
}

VotingActions::~VotingActions() {

}

/******** ELECCIONES ******************/
bool VotingActions::getEleccion(unsigned long eleccionId,Eleccion ** eleccion) {
	string str = props->get("workingPath") + props->get("ArchivoElecciones");
	ExtensibleHash* archivoElecciones = new ExtensibleHash(str,
			props->getInt("ArchivoEleccionesBlockSize"));

	char *data = NULL;
	unsigned long data_len = 0;
	bool res = false;

	if (archivoElecciones->get(eleccionId,&data,&data_len) == true) {
		(*eleccion) = new Eleccion();
		(*eleccion)->unpack(data,data_len);
		res= true;
	}

	if (data != NULL) delete data;
	if (archivoElecciones != NULL) delete archivoElecciones;
	return res;
}

int VotingActions::doEleccionesAction(CLIEntity * entity) {
	if (entity->subCommand == CLIEntity::CLI_VER_SUBCOMMAND) {
		cout << "ELECCIONES->VER" <<endl;
		if (entity->recordId == NULL) {
			cerr << "Número de registro es obligatorio." << endl;
		}
		else {
			unsigned long id = strtoul(entity->recordId,NULL,0);
			Eleccion *eleccion = NULL;
			if (getEleccion(id,&eleccion)==true) {
				char fecha[32];
				sprintf(fecha,"%lu",eleccion->getFecha());
				cout << "Fecha elección: " << fecha << endl;
				delete eleccion;
			}
			else {
				cerr << "No se ha encontrado la elección." << endl;
			}
		}
	}
	else if (entity->subCommand == CLIEntity::CLI_BORRAR_SUBCOMMAND) {

	}
	else if (entity->subCommand == CLIEntity::CLI_INSERTAR_SUBCOMMAND) {
		unsigned long recordsAdded = 0;
		unsigned long recordsUpdated = 0;
		unsigned long recordsError = 0;
		recordsError = addElecciones(entity->fileName,&recordsAdded,&recordsUpdated);

		// imprimir salida
		cout << "ELECCIONES->INSERTAR" <<endl;
		cout << "insertados: " << recordsAdded << endl;
		cout << "actualizados: " << recordsUpdated << endl;
		cout << "con error: " << recordsError << endl;
	}
	return 0;
}

unsigned long VotingActions::addElecciones(string eleccionesFile,
		unsigned long* eleccionesAdded, unsigned long* eleccionesUpdated) {
	EleccionParser* parser = new EleccionParser();

	unsigned long qtyOk = 0, qtyFail = 0;
	vector<Eleccion> elecciones = parser->parse(eleccionesFile, &qtyOk,
			&qtyFail);
	ExtensibleHash* archivoElecciones = NULL;

	(*eleccionesAdded) = 0;
	(*eleccionesUpdated) = 0;
	if (elecciones.size() > 0) {

		string str = props->get("workingPath")
				+ props->get("ArchivoElecciones");
		archivoElecciones = new ExtensibleHash(str,
				props->getInt("ArchivoEleccionesBlockSize"));
		
		CountingMgr* archivoDeConteo = new CountingMgr(props->get("workingPath") +props->get("ArchivoDeConteo"));

		for (unsigned int i = 0; i < elecciones.size(); i++) {
			Eleccion eleccion = elecciones.at(i);

			// buscamos el registro en el archivo de distritos
			unsigned long eleccionDataLen = 0;
			char * eleccionData = NULL;
			bool found = archivoElecciones->get(eleccion.getId(), &eleccionData,
					&eleccionDataLen);

			if (found == false) {
				/// hacemos el add si no existe				
				bool added = archivoElecciones->put(eleccion.getId(),
						eleccion.pack(), eleccion.packLen());

				if (added) {
					(*eleccionesAdded)++;

					// creo los registros en counting, y los indices
					// aqui ya tienen que estar cargados los distritos y las listas
					if (archivoDeConteo->createCountingRegistersForEleccion(&eleccion) == false) {
						cerr << "No se pudo crear la entrada en el archivo de conteo" << endl;
					}
				}
				else {
					qtyFail++;
				}
			} else {
				/*
				/// hacemos el update si existe
				bool added = archivoElecciones->put(eleccion.getId(),
						eleccion.pack(), eleccion.packLen());

				if (added) {
					(*eleccionesUpdated)++;
				}
				else {
					qtyFail++;
				}
				*/
				cerr << "No se puede actualizar los datos de una eleccion" <<endl;
			}

			if (eleccionData != NULL) delete eleccionData;
		}
	}

	delete archivoElecciones;
	delete parser;

	return qtyFail;
}
/****************************************/

/************ DISTRITOS  ****************/
bool VotingActions::getDistrito(unsigned long distritoId,Distrito ** distrito) {
	string str = props->get("workingPath") + props->get("ArchivoDistritos");

	//KIMI CHANGE TO TREE
	BTree* archivoDistritos = new BTree(str,
			props->getInt("ArchivoDistritosBlockSize"));
	/*
	ExtensibleHash* archivoDistritos = new ExtensibleHash(str,
			props->getInt("ArchivoDistritosBlockSize"));
	 */

	char *data = NULL;
	unsigned long data_len = 0;
	bool res = false;
	if (archivoDistritos->get(distritoId,&data,&data_len) == true) {
		(*distrito) = new Distrito();
		(*distrito)->unpack(data,data_len);

		res = true;
	}

	if (data != NULL) delete data;
	if (archivoDistritos != NULL) delete archivoDistritos;
	return res;
}

unsigned long VotingActions::addDistritos(string distritosFile,
		unsigned long* distritosAdded, unsigned long* distritosUpdated) {
	DistritoParser* parser = new DistritoParser();

	unsigned long qtyOk = 0, qtyFail = 0;
	vector<Distrito> distritos = parser->parse(distritosFile, &qtyOk, &qtyFail);
	BTree* archivoDistritos = NULL;

	(*distritosAdded) = 0;
	(*distritosUpdated) = 0;
	if (distritos.size() > 0) {

		string str = props->get("workingPath") + props->get("ArchivoDistritos");
		//KIMI CHANGE TO TREE
		archivoDistritos = new BTree(str,
				props->getInt("ArchivoDistritosBlockSize"));
		/*
		ExtensibleHash* archivoDistritos = new ExtensibleHash(str,
				props->getInt("ArchivoDistritosBlockSize"));
		 */
		for (unsigned int i = 0; i < distritos.size(); i++) {
			Distrito distrito = distritos.at(i);

			// buscamos el registro en el archivo de distritos
			unsigned long distritoDataLen = 0;
			char * distritoData = NULL;
			bool found = archivoDistritos->get(distrito.getDistritoId(),
					&distritoData, &distritoDataLen);

			if (found == false) {
				/// hacemos el add si no existe
				bool added = archivoDistritos->put(distrito.getDistritoId(),
						distrito.pack(), distrito.packLen());

				if (added) {
					(*distritosAdded)++;
				}
				else {
					qtyFail++;
				}
			} else {
				/// hacemos el update si existe
				bool added = archivoDistritos->put(distrito.getDistritoId(),
						distrito.pack(), distrito.packLen());

				if (added) {
					(*distritosUpdated)++;
				}
				else {
					qtyFail++;
				}
			}

			if (distritoData != NULL) delete distritoData;
		}
	}

	if (archivoDistritos != NULL) {
		delete archivoDistritos;
	}
	delete parser;
	return qtyFail;
}

int VotingActions::doDistritosAction(CLIEntity * entity) {
	if (entity->subCommand == CLIEntity::CLI_VER_SUBCOMMAND) {
		cout << "DISTRITOS->VER" <<endl;
		if (entity->recordId == NULL) {
			cerr << "Número de registro es obligatorio." << endl;
		}
		else {
			unsigned long id = strtoul(entity->recordId,NULL,0);
			cout << "Distrito ID: " << id << endl;
			Distrito *distrito = NULL;
			if (getDistrito(id,&distrito)==true) {
				cout << "Distrito: " << distrito->getNombreDist() << endl;
				delete distrito;
			}
			else {
				cerr << "No se ha encontrado el distrito." << endl;
			}
		}
	}
	else if (entity->subCommand == CLIEntity::CLI_BORRAR_SUBCOMMAND) {

	}
	else if (entity->subCommand == CLIEntity::CLI_INSERTAR_SUBCOMMAND) {
		unsigned long recordsAdded = 0;
		unsigned long recordsUpdated = 0;
		unsigned long recordsError = 0;
		recordsError = addDistritos(entity->fileName,&recordsAdded,&recordsUpdated);

		// imprimir salida
		cout << "DISTRITOS->INSERTAR" <<endl;
		cout << "insertados: " << recordsAdded << endl;
		cout << "actualizados: " << recordsUpdated << endl;
		cout << "con error: " << recordsError << endl;
	}
	return 0;
}

/***************************************/

/************ VOTANTES *****************/
unsigned long VotingActions::addVotantes(string votantesFile,unsigned long* votantesAdded, unsigned long* votantesUpdated) {
	VotantesParser* parser = new VotantesParser();
	unsigned long qtyOk = 0, qtyFail = 0;

	vector<Votante> votantes = parser->parse(votantesFile, &qtyOk, &qtyFail,props);
	ExtensibleHash* archivoVotantes = NULL;

	(*votantesAdded) = 0;
	(*votantesUpdated) = 0;

	string _str = props->get("workingPath") + props->get("ArchivoVotantes");

	if (votantes.size() > 0) {

		archivoVotantes = new ExtensibleHash(_str,
				props->getInt("ArchivoVotantesBlockSize"));

		for (unsigned int i = 0; i < votantes.size(); i++) {
			Votante votante = votantes.at(i);

	//		cout << "votante: "<<i << endl;

			unsigned long distritoDataLen = 0;
			char * distritoData = NULL;
			bool found = archivoVotantes->get(votante.getDni(),
					&distritoData, &distritoDataLen);

			if (found == false) {
	//			cout << "not found" << endl;

				/// hacemos el add si no existe
				bool added = archivoVotantes->put(votante.getDni(),
						votante.pack(), votante.packLen());
				if (added) {
					(*votantesAdded)++;
				}
				else {
					qtyFail++;
				}
			} else {
	//			cout << "found" << endl;

				/// hacemos el update si existe
				bool added = archivoVotantes->put(votante.getDni(),
						votante.pack(), votante.packLen());
				if (added) {
					(*votantesUpdated)++;
				}
				else {
					qtyFail++;
				}
			}

			if (distritoData != NULL) delete distritoData;
		}

	}
	delete parser;
	delete archivoVotantes;
	return qtyFail;
}

bool VotingActions::getVotante(unsigned long votanteId,Votante ** votante) {
	string str = props->get("workingPath") + props->get("ArchivoVotantes");
	ExtensibleHash* archivoVotantes = new ExtensibleHash(str,
			props->getInt("ArchivoVotantesBlockSize"));

	char *data = NULL;
	unsigned long data_len = 0;
	bool res = false;
	if (archivoVotantes->get(votanteId,&data,&data_len) == true) {
		(*votante) = new Votante();
		(*votante)->unpack(data,data_len);

		res = true;
	}

	if (data != NULL) delete data;
	if (archivoVotantes != NULL) delete archivoVotantes;
	return res;
}

int VotingActions::doVotantesAction(CLIEntity * entity) {
	if (entity->subCommand == CLIEntity::CLI_VER_SUBCOMMAND) {
		cout << "VOTANTES->VER" <<endl;
		if (entity->recordId == NULL) {
			cerr << "Número de registro es obligatorio." << endl;
		}
		else {
			unsigned long id = strtoul(entity->recordId,NULL,0);
			Votante *votante = NULL;
			if (getVotante(id,&votante)==true) {
				cout << "VOTANTE: " << votante->getNombreApellido() << endl;
				delete votante;
			}
			else {
				cerr << "No se ha encontrado el votante." << endl;
			}
		}
	}
	else if (entity->subCommand == CLIEntity::CLI_BORRAR_SUBCOMMAND) {

	}
	else if (entity->subCommand == CLIEntity::CLI_INSERTAR_SUBCOMMAND) {
		unsigned long recordsAdded = 0;
		unsigned long recordsUpdated = 0;
		unsigned long recordsError = 0;
		recordsError = addVotantes(entity->fileName,&recordsAdded,&recordsUpdated);

		// imprimir salida
		cout << "VOTANTES->INSERTAR" <<endl;
		cout << "insertados: " << recordsAdded << endl;
		cout << "actualizados: " << recordsUpdated << endl;
		cout << "con error: " << recordsError << endl;
	}
	return 0;
}
/**************************************/


/****** CARGOS ***********************/
unsigned long VotingActions::addCargos(string cargosFile,unsigned long* cargosAdded, unsigned long* cargosUpdated) {
	CargoParser* parser = new CargoParser();

	unsigned long qtyOk = 0, qtyFail = 0;
	vector<Cargo> cargos = parser->parse(cargosFile, &qtyOk, &qtyFail);
	BTree* archivoCargos = NULL;

	(*cargosAdded) = 0;
	(*cargosUpdated) = 0;
	if (cargos.size() > 0) {
		string str = props->get("workingPath") + props->get("ArchivoCargos");
		archivoCargos = new BTree(str,
				props->getInt("ArchivoCargosBlockSize"));

		for (unsigned int i = 0; i < cargos.size(); i++) {
			Cargo cargo = cargos.at(i);
			// buscamos el registro en el archivo de distritos
			unsigned long distritoDataLen = 0;
			char * distritoData = NULL;
			bool found = archivoCargos->get(cargo.getCargoId(),
					&distritoData, &distritoDataLen);

			if (found == false) {
				/// hacemos el add si no existe
				bool added = archivoCargos->put(cargo.getCargoId(),
						cargo.pack(), cargo.packLen());
				if (added) {
					(*cargosAdded)++;
				}
				else {
					qtyFail++;
				}
			} else {
				/// hacemos el update si existe
				bool added = archivoCargos->put(cargo.getCargoId(),
						cargo.pack(), cargo.packLen());
				if (added) {
					(*cargosUpdated)++;
				}
				else {
					qtyFail++;
				}
			}

			if (distritoData != NULL) delete distritoData;
		}
	}

	delete archivoCargos;
	delete parser;
	return qtyFail;
}

bool VotingActions::getCargo(unsigned long cargoId,Cargo ** cargo) {
	string str = props->get("workingPath") + props->get("ArchivoCargos");
	BTree* archivoCargos = new BTree(str,
			props->getInt("ArchivoCargosBlockSize"));

	char *data = NULL;
	unsigned long data_len = 0;
	bool res = false;
	if (archivoCargos->get(cargoId,&data,&data_len) == true) {
		(*cargo) = new Cargo();
		(*cargo)->unpack(data,data_len);
		res = true;
	}

	if (data != NULL) delete data;
	if (archivoCargos != NULL) delete archivoCargos;
	return res;
}

int VotingActions::doCargosAction(CLIEntity * entity) {
	if (entity->subCommand == CLIEntity::CLI_VER_SUBCOMMAND) {
		cout << "CARGOS->VER" <<endl;
		if (entity->recordId == NULL) {
			cerr << "Número de registro es obligatorio." << endl;
		}
		else {
			unsigned long id = strtoul(entity->recordId,NULL,0);
			Votante *votante = NULL;
			if (getVotante(id,&votante)==true) {
				cout << "CARGO: " << votante->getNombreApellido() << endl;
				delete votante;
			}
			else {
				cerr << "No se ha encontrado el cargo." << endl;
			}
		}
	}
	else if (entity->subCommand == CLIEntity::CLI_BORRAR_SUBCOMMAND) {

	}
	else if (entity->subCommand == CLIEntity::CLI_INSERTAR_SUBCOMMAND) {
		unsigned long recordsAdded = 0;
		unsigned long recordsUpdated = 0;
		unsigned long recordsError = 0;
		recordsError = addCargos(entity->fileName,&recordsAdded,&recordsUpdated);

		// imprimir salida
		cout << "CARGOS->INSERTAR" <<endl;
		cout << "insertados: " << recordsAdded << endl;
		cout << "actualizados: " << recordsUpdated << endl;
		cout << "con error: " << recordsError << endl;
	}
	return 0;
}
/************************************/

/********* LISTAS *******************/
unsigned long VotingActions::addListas(string listaFile,unsigned long* listasAdded, unsigned long* listasUpdated) {
	ListaParser* parser = new ListaParser();

	unsigned long qtyOk = 0, qtyFail = 0;
	vector<Lista> listas = parser->parse(listaFile, &qtyOk, &qtyFail);
	ExtensibleHash* archivoListas = NULL;

	(*listasAdded) = 0;
	(*listasUpdated) = 0;

	if (listas.size() > 0) {
		string str = props->get("workingPath") + props->get("ArchivoListas");

		archivoListas = new ExtensibleHash(str,
				props->getInt("ArchivoListasBlockSize"));

		CountingMgr* archivoDeConteo = new CountingMgr(props->get("workingPath") +props->get("ArchivoDeConteo"));

		for (unsigned int i = 0; i < listas.size(); i++) {
			Lista lista = listas.at(i);
			// buscamos el registro en el archivo de distritos
			unsigned long listaDataLen = 0;
			char * listaData = NULL;
			bool found = archivoListas->get(lista.getId(),
					&listaData, &listaDataLen);

			if (found == false) {
				/// hacemos el add si no existe
				bool added = archivoListas->put(lista.getId(),
						lista.pack(), lista.packLen());
				if (added) {
					(*listasAdded)++;

					// lo agrego al indice de Counting
					if (archivoDeConteo->addListaEnEleccion(lista.getIdEleccion(),lista.getId(),lista.getNombreLista())) {
						// archivo de conteo actualizado
						//cout << "Actualizando Lista/Eleccion" <<endl;
					}
					else {
						cerr << "Error al actualizar Lista/Eleccion" <<endl;
					}
				}
				else {
					qtyFail++;
				}
			} else {
				/// hacemos el update si existe
				bool added = archivoListas->put(lista.getId(),
						lista.pack(), lista.packLen());
				if (added) {
					(*listasUpdated)++;
				}
				else {
					qtyFail++;
				}
			}

			if (listaData != NULL) delete listaData;
		}
	}

	delete archivoListas;
	delete parser;
	return qtyFail;
}
bool VotingActions::getLista(unsigned long listasId,Lista ** listas) {
	string str = props->get("workingPath") + props->get("ArchivoListas");
	ExtensibleHash* archivoListas = new ExtensibleHash(str,
			props->getInt("ArchivoListasBlockSize"));

	char *data = NULL;
	unsigned long data_len = 0;
	bool res = false;
	if (archivoListas->get(listasId,&data,&data_len) == true) {
		(*listas) = new Lista();
		(*listas)->unpack(data,data_len);
		res = true;
	}

	if (data != NULL) delete data;
	if (archivoListas != NULL) delete archivoListas;
	return res;
}
int VotingActions::doListasAction(CLIEntity * entity) {
	if (entity->subCommand == CLIEntity::CLI_VER_SUBCOMMAND) {
		cout << "LISTAS->VER" <<endl;
		if (entity->recordId == NULL) {
			cerr << "Número de registro es obligatorio." << endl;
		}
		else {
			unsigned long id = strtoul(entity->recordId,NULL,0);
			Lista *lista = NULL;
			if (getLista(id,&lista)==true) {
				cout << "LISTA: " << lista->getNombreLista() << endl;
				delete lista;
			}
			else {
				cerr << "No se ha encontrado la lista." << endl;
			}
		}
	}
	else if (entity->subCommand == CLIEntity::CLI_BORRAR_SUBCOMMAND) {

	}
	else if (entity->subCommand == CLIEntity::CLI_INSERTAR_SUBCOMMAND) {
		unsigned long recordsAdded = 0;
		unsigned long recordsUpdated = 0;
		unsigned long recordsError = 0;
		recordsError = addListas(entity->fileName,&recordsAdded,&recordsUpdated);

		// imprimir salida
		cout << "LISTAS->INSERTAR" <<endl;
		cout << "insertados: " << recordsAdded << endl;
		cout << "actualizados: " << recordsUpdated << endl;
		cout << "con error: " << recordsError << endl;
	}
	return 0;
}
/***********************************/

/********** CANDIDATOS *************/
unsigned long VotingActions::addCandidatos(string candidatosFile,unsigned long* candidatosAdded, unsigned long* candidatosUpdated) {
	CandidatoParser* parser = new CandidatoParser();

	unsigned long qtyOk = 0, qtyFail = 0;
	vector<Candidato> candidatos = parser->parse(candidatosFile, &qtyOk, &qtyFail);
	ExtensibleHash*  archivoCandidatos= NULL;

	(*candidatosAdded) = 0;
	(*candidatosUpdated) = 0;

	if (candidatos.size() > 0) {
		string str = props->get("workingPath") + props->get("ArchivoCandidatos");

		archivoCandidatos = new ExtensibleHash(str,
				props->getInt("ArchivoCandidatosBlockSize"));

		for (unsigned int i = 0; i < candidatos.size(); i++) {
			Candidato candidato = candidatos.at(i);
			// buscamos el registro en el archivo de distritos
			unsigned long candidatoDataLen = 0;
			char * candidatoData = NULL;
			bool found = archivoCandidatos->get(candidato.getId(),
					&candidatoData, &candidatoDataLen);

			if (found == false) {
				/// hacemos el add si no existe
				bool added = archivoCandidatos->put(candidato.getId(),
						candidato.pack(), candidato.packLen());
				if (added) {
					(*candidatosAdded)++;
				}
				else {
					qtyFail++;
				}
			} else {
				/// hacemos el update si existe
				bool added = archivoCandidatos->put(candidato.getId(),
						candidato.pack(), candidato.packLen());
				if (added) {
					(*candidatosUpdated)++;
				}
				else {
					qtyFail++;
				}
			}

			if (candidatoData != NULL) delete candidatoData;
		}
	}

	delete archivoCandidatos;
	delete parser;
	return qtyFail;
}
bool VotingActions::getCandidato(unsigned long candidatoId,Candidato ** candidato) {
	return false;
}
int VotingActions::doCandidatosAction(CLIEntity * entity) {
	if (entity->subCommand == CLIEntity::CLI_VER_SUBCOMMAND) {
		cout << "CANDIDATOS->VER" <<endl;
		if (entity->recordId == NULL) {
			cerr << "Número de registro es obligatorio." << endl;
		}
		else {
			unsigned long id = strtoul(entity->recordId,NULL,0);
			Candidato *candidato = NULL;
			if (getCandidato(id,&candidato)==true) {
				char idVotante[32];
				sprintf(idVotante,"%lu",candidato->getIdVotante());
				cout << "CANDIDATO: " << idVotante << endl;
				delete candidato;
			}
			else {
				cerr << "No se ha encontrado el candidato." << endl;
			}
		}
	}
	else if (entity->subCommand == CLIEntity::CLI_BORRAR_SUBCOMMAND) {

	}
	else if (entity->subCommand == CLIEntity::CLI_INSERTAR_SUBCOMMAND) {
		unsigned long recordsAdded = 0;
		unsigned long recordsUpdated = 0;
		unsigned long recordsError = 0;
		recordsError = addCandidatos(entity->fileName,&recordsAdded,&recordsUpdated);

		// imprimir salida
		cout << "CANDIDATOS->INSERTAR" <<endl;
		cout << "insertados: " << recordsAdded << endl;
		cout << "actualizados: " << recordsUpdated << endl;
		cout << "con error: " << recordsError << endl;
	}
	return 0;
}
/**********************************/


/************* VOTAR **************/
bool VotingActions::votar(CLIEntity *entity) {
	bool res = false;

	cout << "Ingrese su número de documento: " << endl;
	unsigned long dni;
	cin >> dni;

	string password;
	cout << "Ingrese su contraseña: " << endl;
	cin >> password;

	// consultar su esta en el padron
	ExtensibleHash* archivoVotantes = NULL;
	ExtensibleHash* archivoCandidatosDatos = NULL;
	
	BTree* archivoDistrito = NULL;
	BTree* archivoCargos = NULL;

	string str = props->get("workingPath") + props->get("ArchivoVotantes");
	archivoVotantes = new ExtensibleHash(str,props->getInt("ArchivoVotantesBlockSize"));

	str = props->get("workingPath") + props->get("ArchivoVotantes");
	archivoCandidatosDatos = new ExtensibleHash(str,props->getInt("ArchivoVotantesBlockSize"));

	str = props->get("workingPath") + props->get("ArchivoDistritos");
	archivoDistrito = new BTree(str,props->getInt("ArchivoDistritosBlockSize"));

	str = props->get("workingPath") + props->get("ArchivoCargos");
	archivoCargos = new BTree(str,props->getInt("ArchivoCargosBlockSize"));

	CountingMgr *countMgr = new CountingMgr(props->get("workingPath") + props->get("ArchivoDeConteo"));

	char* data = NULL;
	unsigned long data_len = 0;
	if (archivoVotantes->get(dni,&data,&data_len) == false) {
		// si no esta en el padron, mostrar error... y salir.
		cerr << "El votante no se encuentra en el padrón" << endl;
		res = false;
	}
	else {
		// si esta en el padron, muestro el menú de votación
		Votante *votante = new Votante();
		if (votante->unpack(data,data_len)) {

			delete data;

			data = NULL;
			data_len = 0;
			Distrito *distrito = new Distrito();

			if (archivoDistrito->get(votante->getDistritoId(),&data,&data_len) == true) {
				distrito->unpack(data,data_len);

				cout << "Bienvenido " << votante->getNombreApellido() << endl;
				char _dni[32];
				char _distrito[32];
				sprintf(_dni,"%lu",votante->getDni());
				sprintf(_distrito,"%lu - %s",votante->getDistritoId(),distrito->getNombreDist().c_str());
				cout << "> DNI: " << _dni << endl;
				cout << "> Distrito: " << _distrito << endl;

				vector<Eleccion> eleccionesDisponibles = votingHelper->getEleccionesDisponiblesParaVotante(votante);
				
				if (eleccionesDisponibles.size() == 0) {
					cout << "No hay elecciones disponibles para este votante" <<endl;
				}
				else {
					cout << ">> Elecciones disponibles" << endl;

					for (unsigned long i = 0; i < eleccionesDisponibles.size(); i++) {
						Eleccion eleccion = eleccionesDisponibles.at(i);

						Cargo *cargo = NULL;
						if (archivoCargos-getCargo(eleccion.getCargoPrincipalId(),&cargo) == false) {
							cerr << "No existe el cargo principal de la elección" << endl;
						}
						else {
							char _aux[128];
							sprintf(_aux,"%lu] Fecha: %lu ",i+1,eleccion.getFecha());
							cout << _aux << " - " << cargo->getCargo() << endl;
						}

					}

					unsigned long indexEleccion = -1;
					bool quiereVotar = true;

					// esperamos que elija una elección
					while (indexEleccion == -1) {
						cout << "Ingrese el número de elección, o 0 para salir sin votar."<< endl;
						cin >> indexEleccion;
						if (indexEleccion == -1) {
							quiereVotar = false;
							break;
						}
						if (indexEleccion <= eleccionesDisponibles.size() && indexEleccion >=1) {
							quiereVotar = true;
							break;
						}
					}

					if (quiereVotar == true) {
						indexEleccion--;
						char _aux[128];
						sprintf(_aux,"%lu - Fecha: %lu",indexEleccion+1,eleccionesDisponibles.at(indexEleccion).getFecha());
						cout << "Elección seleccionada: " << _aux << endl;

						// obtenemos las listas y candidatos de esta elección
						bool seleccionConfirmada = false;

						// claves para recuperar el registro de conteo.
						unsigned long listaVotada = -1;
						unsigned long eleccionVotada = eleccionesDisponibles.at(indexEleccion).getId();
						unsigned long distritoVotado = votante->getDistritoId();

						cout << ">> Listas y Candidatos disponibles" <<endl;

						vector <unsigned long> listasId = countMgr->getListasParaEleccion(
								eleccionVotada);

//						vector<Lista> listas = countMgr->convertListIDsIntoList(listasId);

 						while (seleccionConfirmada == false) {
 							
							unsigned long cantListas = listasId.size();
							for (unsigned long i = 0; i<cantListas; i++) {
								//Lista list = listas.at(i);
								Lista *list = NULL;
								if (getLista(listasId.at(i),&list) == false)
									continue;

								char _aux[17];
								sprintf(_aux,"%lu",i+1);
								cout << _aux <<"] Lista: " << list->getNombreLista() << endl;
								
								vector<Candidato> candidatos = votingHelper->getCandidatosEnLista(listasId.at(i));
								for (int c=0; c<candidatos.size(); c++){
									Candidato cand = candidatos.at(c);
									unsigned long dniCandidato = cand.getIdVotante();
									string nombreApellido;
									data = NULL;
									data_len = 0;
									
									if (archivoCandidatosDatos->get(dniCandidato,&data,&data_len) == true) {
										Votante* datosCandidato = new Votante();
										
										if (datosCandidato->unpack(data,data_len)) {
											nombreApellido = datosCandidato->getNombreApellido();
										}									
									}
									cout<<"Candidato: "<<dniCandidato<<"-"<<nombreApellido<<endl;
								}									
								delete list;
							}

							cout << "Ingrese el número de lista, o 0 para salir sin votar."<< endl;

							cin >> listaVotada;

							if (listaVotada == 0) {
								quiereVotar = false;
								break;
							}

							if (listaVotada > 0 && listaVotada <= listasId.size()) {
								listaVotada--;

								//Lista list = listas.at(listaVotada);
								Lista *list = NULL;
								getLista(listasId.at(listaVotada),&list);


								// confirmar
								cout << "¿Confirma la votación de la Lista " << list->getNombreLista() << "?" << endl;
								cout << "Ingrese 1 para confirmar positivamente. Cualquier otra entrada para modificar su voto." << endl;

								unsigned long temp = 0;
								cin >> temp;

								if (temp == 1) {
									seleccionConfirmada = true;
									listaVotada = list->getId();
								}
							}
						}

						// recuperamos conteo, y guardamos el voto!
						if (countMgr->incrementCountOnRegister(eleccionVotada,distritoVotado,listaVotada)) {
							// guardamos la eleccion en el votante
							votante->addEleccion(eleccionVotada);

							bool updated = archivoVotantes->put(votante->getDni(),
								votante->pack(), votante->packLen());
							if (updated) {
								cout << "Su voto se ha registrado correctamente." << endl;
							}
							else {
								cerr << "Se ha registrado el voto, pero no se ha podido actualizar la información en el padrón" << endl;
							}
						}
						else {
							cout << "Su voto NO se ha podido registrar" << endl;
						}
					}
					else {
						cout << "Se ha retirado sin votar." <<endl;
					}
				}
			}
			else {
				cerr << "El distrito del votante no se encuentra en el sistema" << endl;
				res = false;
			}
		}
		else {
			cerr << "No se ha podido recuperar el registro Votante correctamente" << endl;
		}
	}

	delete countMgr;
	delete archivoDistrito;
	delete archivoVotantes;
	delete archivoCargos;
	return res;
}

bool VotingActions::ingresarVotosDesdeArchivo(string filePath) {
	bool res = false;
	VotoAutomaticoParser* parser = new VotoAutomaticoParser();

	unsigned long qtyOk = 0, qtyFail = 0;

	unsigned long inhabilitadosPorDistrito = 0;
	unsigned long inhabilitadosYaVotaron = 0;
	unsigned long inhabilitadosClaveIncorrecta = 0;

	vector<Voto> votos = parser->parse(filePath, &qtyOk, &qtyFail);

	if (votos.size() > 0) {
		string str = props->get("workingPath") + props->get("ArchivoVotantes");

		ExtensibleHash *archivoVotantes = new ExtensibleHash(str,props->getInt("ArchivoVotantesBlockSize"));
		CountingMgr* archivoDeConteo = new CountingMgr(props->get("workingPath") +props->get("ArchivoDeConteo"));

		str = props->get("workingPath") + props->get("ArchivoElecciones");
		ExtensibleHash *archivoElecciones = new ExtensibleHash(str,props->getInt("ArchivoEleccionesBlockSize"));

		for (unsigned long i = 0; i < votos.size(); i++) {
			Voto voto = votos.at(i);

			char* data = NULL;
			unsigned long data_len = 0;
			if (archivoVotantes->get(voto.getVotanteId(),&data,&data_len) == false) {
				cerr << "Error al obtener el votante: " << voto.getVotanteId() <<endl;
				qtyFail++;
			}
			else {
				Votante *votante = new Votante();
				votante->unpack(data,data_len);
				free(data);
				data = NULL;

				bool canVote = true;

				string claveVoto = voto.getClave();
				string claveVotoEncriptada;

				RSA* rsa = new RSA(props->getInt("RSA_KEY_LENGTH"));
				string pubKeyFile = props->get("RSA_PUBLIC_KEY_FILE");
				Properties* key = new Properties(pubKeyFile);
				if (key->load() == false) {
					delete rsa;
					delete key;
					rsa = NULL;
					key = NULL;
					cerr << "No se pudo cargar el archivo con la clave privada" << endl;
					claveVotoEncriptada = "";
				}
				unsigned long n = key->getInt("N");
				unsigned long e = key->getInt("E");

				claveVotoEncriptada = rsa->encrypt(e,n,claveVoto);

			//	cout << "Ingreso "<< claveVoto << " - " << claveVotoEncriptada << endl;
			//	cout << "clave Votante en file " << votante->getClaveEncriptada() << endl;

				if (votante->getClaveEncriptada() != claveVotoEncriptada) {
					inhabilitadosClaveIncorrecta++;
					canVote = false;
			//		cerr << "Clave voto: " << claveVoto << " - claveVotante " << votante->getClaveEncriptada() << " - "
			//				<< " encriptado " << claveVotoEncriptada << endl;
				}
				if (key != NULL)
					delete key;
				if (rsa != NULL)
					delete rsa;

				unsigned long distrito = votante->getDistritoId();

				// chequeamos que el distrito del votante corresponda con la elección
				if (canVote) {
					Eleccion *e = new Eleccion();
					if (archivoElecciones->get(voto.getEleccionId(),&data,&data_len) == false) {
						canVote = false;
						cerr << "No se ha podido obtener la elección indicada" <<endl;
					}
					else {
						e->unpack(data,data_len);
						bool found = false;
						for (unsigned long j = 0; j < e->getDistritos().size(); j++) {
							if (e->getDistrito(j) == distrito) {
								found = true;
								break;
							}
						}
						free(data);
						data = NULL;

						if (found == false) {
							canVote = false;
							inhabilitadosPorDistrito++;
							cerr << "Votante: " << votante->getDni() << " distrito erroneo. Eleccion: " << e->getId() << endl;
						}
					}
					delete e;
				}

				if (canVote) {
					for (unsigned long j = 0; j < votante->getElecciones().size(); j++) {
						if (votante->getElecciones().at(j) == voto.getEleccionId()) {
							canVote = false;
							inhabilitadosYaVotaron++;
							break;
						}
					}
				}

				if (canVote) {
					if (archivoDeConteo->incrementCountOnRegister(voto.getEleccionId(),distrito,voto.getListaId())) {
						qtyOk++;

						votante->addEleccion(voto.getEleccionId());

						bool updated = archivoVotantes->put(votante->getDni(),
							votante->pack(), votante->packLen());
						if (updated) {
//							cout << "El voto se ha registrado correctamente." << endl;
						}
						else {
							cerr << "Se ha registrado el voto, pero no se ha podido actualizar la información en el padrón" << endl;
						}
					}
					else {
//						cerr << "No se ha registrado el voto de forma correcta." << endl;
						qtyFail++;
					}
				}
				else {
					qtyFail++;
					//cout << "NO: " << votante->getDni() << endl;
				}
				delete votante;
			}
		}

		delete archivoVotantes;
	}

	cout << "Votos ingresados correctamente: ";
	char _aux_[24];
	sprintf(_aux_,"%lu",qtyOk);
	cout << _aux_ << endl;
	cout << "----------------------------------------------------" <<endl;
	cout << "Votos que no se han podido ingresar: ";
	sprintf(_aux_,"%lu",qtyFail);
	cout << _aux_ << endl;

	cout << "> por clave incorrecta: ";
	sprintf(_aux_,"%lu",inhabilitadosClaveIncorrecta);
	cout << _aux_ << endl;

	cout << "> por distrito no corresponde con la elección: ";
	sprintf(_aux_,"%lu",inhabilitadosPorDistrito);
	cout << _aux_ << endl;

	cout << "> por ya haber votado: ";
	sprintf(_aux_,"%lu",inhabilitadosYaVotaron);
	cout << _aux_ << endl;


	delete parser;
	return res;
}

bool VotingActions::encriptarArchivoDeAdministradores() {
	bool res = false;

	// Ejecutar una unica vez, y con el archivo en texto plano!
	string adminFilePath = props->get("ArchivoAdministradoresPath");

	RSA* rsa = new RSA(props->getInt("RSA_KEY_LENGTH"));
	unsigned long n,phi;
 	rsa->generateNAndPhi(&n,&phi);
	unsigned long pk, pu;
	rsa->generatePrivateAndPublicKey(n,phi,&pk,&pu);

	string privFile = props->get("RSA_PRIVATE_KEY_FILE");
	string pubFile = props->get("RSA_PUBLIC_KEY_FILE");

	res = rsa->createPrivateKeyFile(privFile,pk,n);
	if (!res) {
		cerr << "Error al crear archivo de clave privada" <<endl;
	}
	res = rsa->createPublicKeyFile(pubFile,pu,n);
	if (!res) {
		cerr << "Error al crear archivo de clave publica" <<endl;
	}

	string encryptedAdminFilePath = adminFilePath + "_rsa";
	res = rsa->encrypt(pu,n,adminFilePath,encryptedAdminFilePath);

	props->put("ArchivoAdministradoresPath",encryptedAdminFilePath);
	props->save();

	if(remove(adminFilePath.c_str()) != 0) {
		cerr << "No se pudo borrar el archivo de administradores en texto plano." << endl;
		res = false;
	}

	delete rsa;

	res = true;

	cout << "Archivo con clave publica: " <<pubFile << endl;
	cout << "Archivo con clave privada: " << privFile << endl;
	cout << "<<NOTA>> Se usarán estas claves para encriptar/desencriptar el archivo de votantes" << endl;

	return res;
}

bool VotingActions::romperRSAConClavePublica() {
	RSABreaker* breaker = new RSABreaker();

	bool res = breaker->breakByForceAttack(props);

	return res;
}

bool VotingActions::checkSystemIntegrity() {
	bool res = true;  // por defecto todo esta bien
	bool partiallyGood = false;
	bool goodLocal = false;
	//Obtengo todas las elecciones

	vector<Eleccion> elecciones = votingHelper->getTodasLasElecciones();

	//abrimos el archivo de candidatos, para recorrerlo por bloques...
	string str = props->get("workingPath") + props->get("ArchivoCandidatos") + "Records";
	BlocksFile* candidatosBF = new BlocksFile(str,props->getInt("ArchivoCandidatosBlockSize"));

	string _str = props->get("workingPath") + props->get("ArchivoVotantes");
	ExtensibleHash* archivoVotantes = new ExtensibleHash(_str,props->getInt("ArchivoVotantesBlockSize"));

	string str2 = props->get("workingPath") + props->get("ArchivoCargos");
	BTree* archivoCargos = new BTree(str2,props->getInt("ArchivoCargosBlockSize"));


	if ((candidatosBF == NULL) ||(candidatosBF != NULL && candidatosBF->getBlocksCount() == 0)) {
		res = false;
		cerr << "No hay candidatos en el sistema." <<endl;
		delete candidatosBF;
		return res;
	}

	for (unsigned long i = 0; i < elecciones.size(); i++) {
		// obtengo todos los distritos para esta eleccion
		Eleccion e = elecciones.at(i);
		goodLocal = true;

		cout << "Eleccion: " << e.getId() << " - Fecha: " << e.getFecha() << endl;
		cout << e.getDistritos().size() << " distrito(s) participando." << endl;

		// obtenemos todos los cargos para esta eleccion
		unsigned long candidatosEleccion = 1; // el cargo principal
		unsigned long cargoPrincipalId = e.getCargoPrincipalId();

		char* cargoRecord = NULL;
		unsigned long cargoRecordLen = 0;

		if (archivoCargos->get(cargoPrincipalId,&cargoRecord,&cargoRecordLen) == false) {
			cerr << "No se ha podido obtener los cargos para la eleccion: "<< e.getId() << " - Fecha: "<< e.getFecha() << " - Cargo: " << e.getCargoPrincipalId()<< endl;
			continue;
		}

		Cargo cargo;
		// cuanto cantidad de cargos
		if (cargo.unpack(cargoRecord,cargoRecordLen) == false) {
			cerr << "No se ha podido obtener los cargos para la eleccion: "<< e.getId() << " - Fecha: "<< e.getFecha() << " - Cargo: " << e.getCargoPrincipalId()<< endl;
			continue;
		}

		candidatosEleccion += cargo.getCargosSecundarios().size();

		cout << candidatosEleccion << " cargo(s) en juego." << endl;


		vector<unsigned long> distritosParaEleccion = e.getDistritos();

		if (distritosParaEleccion.size() == 0) {
			res = false;
			cerr << ">> La eleccion " << e.getId() << " - Fecha: "<< e.getFecha() << " - Cargo: " << e.getCargoPrincipalId()<< " no tiene distritos asignados" << endl;
			break;
		}

		// para cada distrito obtenemos sus listas
		for (unsigned long j = 0; j < distritosParaEleccion.size(); j++) {
			unsigned long distrito = distritosParaEleccion.at(j);
			vector<Lista> listas = votingHelper->getListasParaEleccionYDistrito(e.getId(),distrito);

			if (listas.size() == 0) {
				cerr << ">> No hay listas en el distrito " << distrito << " para la eleccion " << e.getId() << " - Fecha: " << e.getFecha() << " - Cargo: " << e.getCargoPrincipalId()<< endl;
				res = false;
				continue;
			}

			cout << "\tDistrito: " << distrito << endl;

			unsigned long lista;
			// para cada lista verificamos si todos los cargos estan cubiertos
			for (unsigned long k = 0; k < listas.size(); k++) {

				lista = listas.at(k).getId();

				cout << "\t\tLista: " << lista << endl;

				// recorremos el archivo de candidatos buscando candidatos que pertenezcan a esta lista
				// en este distrito, y contamos la cantidad de candidatos que cumplen la regla
				vector<Candidato> candidatos = votingHelper->getCandidatosEnLista(lista);
				unsigned long candidatosMatch = 0;

				for (unsigned long cIdx = 0; cIdx < candidatos.size(); cIdx++) {
					Candidato c = candidatos.at(cIdx);

					char* recordVot = NULL;
					unsigned long recordVotLen = 0;

					if (archivoVotantes->get(c.getIdVotante(),&recordVot,&recordVotLen)) {
						Votante* v = new Votante;

						if (v->unpack(recordVot,recordVotLen)) {
							if (v->getDistritoId() == distrito) {
								candidatosMatch++;
								cout << "\t\t\tCandidato: " << v->getNombreApellido() << " - DNI: " << v->getDni() << endl;
							}
						}

						delete v;
					}

					if (recordVot != NULL) free (recordVot);
				}

				// verificar si la cantidad de candidatos que matchearon, es igual a la que
				// debe existir para esta eleccion
				if (candidatosMatch != candidatosEleccion) {
					/*
					cerr << "\t\t\tNo se ha encontrado la cantidad de candidatos suficientes para la eleccion: " <<
							e.getId() << " - Fecha: " << e.getFecha() << " - Cargo: " <<
							e.getCargoPrincipalId() << " - Distrito: "<<  distrito <<". "<< candidatosMatch << " != " << candidatosEleccion << endl;
					*/
					cerr << "\t\t\t\tNo se ha encontrado la cantidad requerida de candidatos en esta lista." << endl;
					cerr << "\t\t\t\tEleccion: " << e.getId() << " - Fecha: " << e.getFecha() << " - Cargo: " <<
							e.getCargoPrincipalId() << " - Distrito: "<<  distrito <<". "<< candidatosMatch << " != " << candidatosEleccion << endl;

					goodLocal = false;
					res = false;
				}
				else {
					/*
					cerr << "\t\t\tMatch para la eleccion: " <<
							e.getId() << " - Fecha: " << e.getFecha() << " - Cargo: " <<
							e.getCargoPrincipalId() << " - Distrito: "<<  distrito <<". "<< candidatosMatch << " == " << candidatosEleccion << endl;
					*/
					cout << "\t\t\t\tLa lista " <<lista << " posee la cantidad de candidadtos necesaria." << endl;
					partiallyGood = true;
				}
//				cout << "___ FIN LISTA ___" << endl;
				cout << endl;
			}

//			cout << "___ FIN DISTRITO ___" << endl;
			cout << endl;
		}

//		cout << "___ FIN ELECCION ___" << endl;
		cout << endl;
		cout << "Coherencia datos de Eleccion: " << e.getId() << " " << (goodLocal==true?"SI":"NO") << endl;
		cout << endl;
	}

	if (res == true) {
		cout<< "Los datos del sistema están completos y son coherentes." << endl;
	}
	else {
		if (partiallyGood == true) {
			cout<< "Los datos del sistema están completos y son coherentes de forma parcial. Algunas elecciones pueden no tener todos los datos necesarios." << endl;
		}
		else {
			cerr<< "<<ERROR>> Los datos del sistema están incompletos y/o son incoherentes para todas las elecciones del sistema." << endl;
		}
	}


	delete candidatosBF;
	delete archivoCargos;
	delete archivoVotantes;

	return res;
}

/***** COMMAND LINE INTERFACE *******/
int VotingActions::doAction(int argc, char ** argv) {

	CLI* cli = new CLI();
	CLIEntity* entity = cli->processCommand(argc,argv);
	int res = -1;
	//cout << entity->command << " :: " << entity->subCommand << " :: " << entity->fileName <<endl;

	if (cli->entityRequiresLogin(entity)) {
		AdminManager* adminManager = new AdminManager(props);
		bool login = false;
		if (entity->user != NULL && entity->password != NULL) {
			login = adminManager->login(entity->user,entity->password);
		}
		if (login == false) {
			cerr << "<<ERROR>> Usuario o contraseña incorrecto" <<endl;
			delete adminManager;
			delete entity;
			delete cli;
			return -1;
		}
	}

	if (entity->command == CLIEntity::CLI_INVALID_COMMAND || entity->subCommand == CLIEntity::CLI_INVALID_SUBCOMMAND) {
		// error!!!!!
		cerr << "Comando invalido." << endl;
	}
	else if (entity->command == CLIEntity::CLI_COMPROBAR_INTEGRIDAD){
			checkSystemIntegrity();
	}
	else if (entity->command == CLIEntity::CLI_ROMPER_RSA){
		if (romperRSAConClavePublica()) {
			cout << "Se ha obtenido la clave privada a partir de la clave publlica." << endl;
		}
		else {
			cout << "No se ha podido obtener la clave privada, o ha ocurrido un error." << endl;
		}
	}
	else if (entity->command == CLIEntity::CLI_ENCRIPTAR_ARCHIVO_ADMIN_COMMAND) {
		if (encriptarArchivoDeAdministradores()) {
			cerr << "Archivo de administradores encriptado" << endl;
		}
		else {
			cerr << "Error al encriptar archivo de administradores" << endl;
		}
	}
	else if (entity->command == CLIEntity::CLI_DISTRITOS_COMMAND) {
		doDistritosAction(entity);
	}
	else if (entity->command == CLIEntity::CLI_ELECCIONES_COMMAND) {
		doEleccionesAction(entity);
	}
	else if (entity->command == CLIEntity::CLI_VOTANTES_COMMAND) {
		doVotantesAction(entity);
	}
	else if (entity->command == CLIEntity::CLI_CARGOS_COMMAND) {
		doCargosAction(entity);
	}
	else if (entity->command == CLIEntity::CLI_LISTAS_COMMAND) {
		doListasAction(entity);
	}
	else if (entity->command == CLIEntity::CLI_CANDIDATOS_COMMAND) {
		doCandidatosAction(entity);
	}
	else if (entity->command == CLIEntity::CLI_VOTAR_COMMAND) {
		res = (votar(entity) == true?0:-1);
	}
	else if (entity->command == CLIEntity::CLI_REPORTE_COMMAND) {
		if (entity->subCommand == CLIEntity::CLI_REPORTE_DISTRITO_SUBCOMMAND){
			unsigned long recordId = -1;

			cout << "Reporte por Distrito" << endl;
			cout << "Archivo de salida: "<<entity->fileName <<endl;
			cout << "ID Distrito: " << entity->recordId << endl;
			cout << "*****************************************" << endl;

			recordId = strtoul(entity->recordId,NULL,0);

			Reports *reports = new Reports(props);
			reports->createReportForDistrito(recordId,entity->fileName,props);
		}
		else if (entity->subCommand == CLIEntity::CLI_REPORTE_ELECCION_SUBCOMMAND){
			unsigned long recordId = -1;

			cout << "Reporte por Elección" << endl;
			cout << "Archivo de salida: "<<entity->fileName <<endl;
			cout << "ID Elección: " << entity->recordId << endl;
			cout << "*****************************************" << endl;


			recordId = strtoul(entity->recordId,NULL,0);

			Reports *reports = new Reports(props);
			reports->createReportForEleccion(recordId,entity->fileName,props);
		}
		else if (entity->subCommand == CLIEntity::CLI_REPORTE_LISTA_SUBCOMMAND){
			cout << "Reporte por Lista" << endl;
			cout << "Archivo de salida: "<<entity->fileName <<endl;
			cout << "ID Lista: " << entity->recordId << endl;
			cout << "*****************************************" << endl;

			Reports *reports = new Reports(props);
			reports->createReportForLista(entity->recordId,entity->fileName,props);
		}
	}
	else if (entity->command == CLIEntity::CLI_VOTO_AUTOMATICO_COMMAND) {
		res = ingresarVotosDesdeArchivo(entity->fileName);
	}

	delete cli;
	delete entity;
	return res;
}

/***************************************/
